<?php
/**
 * Alipay.class.php
 *
 * @author  camfee <camfee@foxmail.com>
 *
 */

namespace controls\MobileApi\Payment;

use Center\CoinLog;
use Center\Goods;
use Center\Payment;
use Center\User;
use Common\DataType;
use MobileApi\ApiBase;

/**
 * 阿里云支付 相关接口.
 *
 * @package Payment
 * @author  camfee <camfee@foxmail.com>
 *
 */
class Alipay extends ApiBase
{
    /**
     * 创建预支付订单.
     *
     * <pre>
     * POST
     *      product_id: 购买商品的id
     * </pre>.
     *
     * @return string|void json
     *
     * <pre>
     * {
     *      "Status": 200,
     *      "Result": {
     *          "OrderStr": "OrderStr" //https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.HVXdfB&treeId=204&articleId=105300&docType=1
     *      }
     * }
     *  异常情况
     * 201: 购买的商品不存在
     * 212: 网络错误
     * 213: 数据错误
     * </pre>
     */
    public function create()
    {
        $uid = $this->isLogin(true);
        $product_id = trim($_POST['product_id']);
        $app_id = $GLOBALS['g_appid'];
        $device_id = $GLOBALS['g_deviceid'];
        $channel = $GLOBALS['g_channel'];

        $product_info = Goods::getInfoByIds($product_id);
        if (empty($product_info)) {
            debug_log("Weixin buy {$product_id} not exist");
            $this->output(201, '购买商品不存在');
        }

        $subject = $product_info['Title'];
        $total_amount = $product_info['Price'];
        $out_trade_no = Payment::generateSN($app_id, Payment::PAY_TYPE_ALIPAY, $channel);
        $result = \lib\plugins\alipay\Alipay::tradeAppPay($out_trade_no, $total_amount, $subject);

        if ($result !== false) {
            $params = [
                'AppId' => $app_id,
                'DeviceId' => $device_id,
                'UserId' => $uid,
                'GoodsInfo' => $subject,
                'SN' => $out_trade_no,
                'ProductId' => $product_id,
                'PaymentType' => Payment::PAY_TYPE_ALIPAY,
                'TotalFee' => $total_amount * 100,
                'Status' => Payment::STATUS_WAIT_PAY,
            ];
            $ret = Payment::add($params);
            if ($ret === false) {
                debug_log(["weixin buy addPayment failed, ret: {$ret}", $params], JF_LOG_ERROR);
                $this->output(213, '数据错误');
            }
            debug_log("weixin buy addPayment, uid: {$uid}, appId: {$app_id}, productId: {$product_id}");

            $this->output(200, ['OrderStr' => $result]);
        }
    }

    /**
     * 查询支付订单.
     *
     * <pre>
     * POST
     *      sn: 必选， 订单号
     *      tradeno: 必选， 支付宝订单号
     * </pre>.
     *
     * @return string|void json
     *
     * <pre>
     * {
     * "Status": 200,
     * "Result": "支付成功"
     * }
     * 异常情况
     * 211, '参数错误'
     * 212, '订单不存在'
     * 213, '订单异常'
     * 214, '用户已取消支付'
     * 215, '用户支付失败'
     * 216, '未付款交易超时关闭，或支付完成后全额退款'
     * 217, '正在支付中, 等待买家付款'
     * 218, '交易结束，不可退款'
     * 200, '支付成功'
     * </pre>
     */
    public function query()
    {
        $uid = $this->isLogin(true);
        $sn = $_POST['sn'];
        $trade_no = $_POST['tradeno'];
        if (empty($sn) && empty($trade_no)) {
            $this->output(211, '参数错误');
        }
        $payment_info = Payment::getInfoBySN($sn);
        if (empty($payment_info)) {
            $this->output(212, '订单不存在');
        }

        $payment_id = $payment_info['PaymentId'];
        $product_id = $payment_info['ProductId'];
        $user_id = $payment_info['UserId'];
        $product_info = Goods::getInfoByIds($product_id);

        if (!isset($pay_config[$product_id]) || $uid != $user_id) {
            debug_log("weixin pay query productId:{$product_id} not exist user: $user_id-$uid", JF_LOG_ERROR);
            $this->output(213, '订单异常');
        }

        $paymentPrice = $product_info['Price'];

        $old_status = $payment_info['Status'];
        if ($old_status == Payment::STATUS_PAY_CANCELED) {
            $this->output(214, '用户已取消支付');
        } elseif ($old_status == Payment::STATUS_PAY_FAILURE) {
            $this->output(215, '用户支付失败');
        } elseif ($old_status == Payment::STATUS_PAY_SUCCESS) {
            $this->output(200, '支付成功');
        }

        $result = \lib\plugins\alipay\Alipay::tradeQuery($sn, $trade_no);
        $result = json_decode($result, true);

        $response = $result['alipay_trade_query_response'];
        if ($response['code'] == 10000) {
            $trade_status = $response['trade_status'];

            $responsePrice = $response['total_amount'];
            if ($responsePrice != $paymentPrice) {
                $this->output(213, '订单异常');
            } elseif ($trade_status == 'TRADE_CLOSED') { //未付款交易超时关闭，或支付完成后全额退款
                debug_log("alipay pay query TRADE_CLOSED, paymentId:{$payment_id}, status:{$trade_status}", JF_LOG_WARNING);
                Payment::updatePaymentBySN($sn, ['Status' => Payment::STATUS_PAY_CANCELED]);
                $this->output(216, '未付款交易超时关闭，或支付完成后全额退款');
            } elseif ($trade_status == 'TRADE_SUCCESS') { //交易支付成功
                if (Payment::isFirstPay($uid)) {
                    CoinLog::addCoinLog($uid, 2, CoinLog::TYPE_FIRST_PAY);
                }
                $data = [
                    'ThirdSN' => $response['trade_no'],
                    'Content' => $response['store_name'],
                    'Status' => Payment::STATUS_PAY_SUCCESS,
                    'UpdateTime' => DataType::datetime(),
                ];
                if (Payment::paySuccess($sn, $data) !== false) {
                    $coin = (int)$product_info['JCoin'] + (int)$product_info['Donate'];
                    pay_succ_log("paySuccess, paymentId:{$payment_id}, userId:{$user_id}");
                    if (User::updateJCoin($user_id, $coin) === false) {
                        pay_fail_log("addCoin failed, paymentId:{$payment_id}, userId:{$user_id}, Coin:{$coin}");
                        Payment::updatePaymentBySN($sn, ['Status' => Payment::STATUS_SEND_GOODS_FAILED]);
                    } else {
                        CoinLog::addCoinLog($uid, $product_info['JCoin'], CoinLog::TYPE_EXCHANGE, false);
                        if (!empty($product_info['Donate'])) {
                            CoinLog::addCoinLog($user_id, $product_info['Donate'], CoinLog::TYPE_PAY_DONATE, false);
                        }
                        pay_succ_log("addCoin, paymentId:{$payment_id}, userId:{$user_id}, Coin:{$coin}");
                    }
                } else {
                    pay_fail_log("paySuccess failed, paymentId:{$payment_id}, uid:{$uid}");
                }
                $this->output(200, '支付成功');
            } elseif ($trade_status == 'TRADE_FINISHED') { //交易结束，不可退款
                debug_log("alipay pay query TRADE_FINISHED, paymentId:{$payment_id}, status:{$trade_status}", JF_LOG_WARNING);
                $this->output(218, '交易结束，不可退款');
            } elseif ($trade_status == 'WAIT_BUYER_PAY') { //交易创建，等待买家付款

                debug_log("alipay pay query faild, paymentId:{$payment_id}, status:{$trade_status}", JF_LOG_WARNING);
                $this->output(217, '正在支付中, 等待买家付款');
            }
        } else {
            $this->output($response['code'], $response['msg'] . (isset($response['sub_msg']) ? $response['sub_msg'] : ''));
        }
    }
}
